/*************************************************************************
> File Name: charMapper.cpp
> Author:zhaopeng
> Mail:654018509@qq.com
> Created Time: 2017年03月10日 星期五 22时01分05秒
************************************************************************/

#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
#include <memory.h>

using namespace std;

void setcharArray(char *buffer, int begin, int value, const int valueLen);

void printBinary(char c);

int getISomeBit(int value, int begin, int getlen, const int valueLen);

void testDemo(const string mapper);

void test();

void getStr2Array(char* src, string &str, int valueLen, const string &mapper);

int main(int argc, char* argv[])
{
    string charstr="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    charstr.insert(0, 1, '\0');

    testDemo(charstr);
    return 0;
}

int getISomeBit(int value, int begin, int getlen, const int valueLen)
{
    int temp = (1<<getlen)-1;
    return ((value>>(valueLen-(begin+getlen))) & temp);
}

void splitValue2Array(char *buffer, int begin, int value, const int valueLen)
{
    int beginByte = begin / 8;
    int endByte = ( begin + valueLen - 1) / 8;

    int left2Write = valueLen;
    for(int i=beginByte; i<=endByte; i++)
    {
        int bi = (i==beginByte) ? (begin%8) : 0;
        int aliBits = 8 - bi;
        if(left2Write > aliBits)
        {
            setcharArray(&(buffer[i]), bi, getISomeBit(value, 0, aliBits, valueLen), aliBits);
            left2Write -= aliBits;
        }
        else
        {
            setcharArray(&(buffer[i]), bi, getISomeBit(value, valueLen-left2Write, left2Write, valueLen), left2Write);
            left2Write = 0;
        }
    }
}

void getStr2Array(char* src, string &str, int valueLen, const string &mapper)
{
    bool becontinue = true;
    for(int index=0; becontinue; index++)
    {
        int bi = index * valueLen;
        int byteIndex = bi / 8;
        int byteEnd = (bi + valueLen -1) / 8;
        int left2Read = valueLen;
        int value =  0;

        for(int i=byteIndex; i<=byteEnd; i++)
        {
            bi = (i==byteIndex) ? (bi%8) : 0;
            int aliBits = 8 - bi;

            if(left2Read > aliBits)
            {
                value |= getISomeBit(src[i], bi, aliBits, 8);
                left2Read -= aliBits;
                value = (value<<left2Read);
            }
            else
            {
                value |= getISomeBit(src[i], bi, left2Read, 8);
                left2Read = 0;
            }
        }
        if(value==0)
            becontinue = false;

        char c = mapper.at(value);
        str.append(1,c);

    }
}

void setcharArray(char *buffer, int begin, int value, const int valueLen)
{
    int temp = (1<<valueLen) - 1;
    temp = temp << (8 - valueLen - begin);
    *buffer &= (~temp);
    value = value<<(8-valueLen-begin);
    *buffer |= value;
}

void printBinary(char c)
{
    printf("c:%u\n", c);
    for(int i=7; i>-1; i--)
    {
        printf("%d", (c>>i)&1);
    }
    printf("\n");
}

void test()
{
    char *src[] = {"11010011", "00101100", "11110000", "00100011"};
    char buffer[4];

    for(int i=0; i<4; i++)
    {
        int sum = 0;
        char *p = src[i];

        while(*p)
        {
            sum *= 2;
            sum += *p - '0';
            p++;
        }

        buffer[i] = sum;
    }
    splitValue2Array(buffer, 4, 127, 6);
    printBinary(buffer[0]);
    printf("\n");
    printBinary(buffer[1]);
    printf("\n");
}

void testDemo(const string mapper)
{
    char buffer[20];
    memset(buffer, 0, sizeof(char)*20);
    char *ori = "aA12ghfruijqasdfgtrt";
    for(int i=0; i<20; i++)
    {
        int index = mapper.find_first_of(ori[i]);
        splitValue2Array(buffer, i*6, index, 6);
    }
    string str="";
    getStr2Array(buffer, str, 6, mapper);
    cout<<str<<endl;
}
